#include "model.h"
#include "misc.h"
#include <string>


void  model::LoadObjModel(const char* filePath)
{
	int filesize=0;
	char*fileContent = LoadFileContent(filePath,filesize);
	if (fileContent!=nullptr)
	{
		//obj model decode
		struct VertexInfo
		{
			float v[3];
		};

		struct VertexDefine
		{
			int positionIndex;
			int texcoordIndex;
			int normalIndex;
		};
		std::vector<VertexInfo> positions;
		std::vector<VertexInfo> texcoords;
		std::vector<VertexInfo> normals;

		std::vector<unsigned int> objIndexes;// -> opengl indexes
		std::vector<VertexDefine> vertices;// -> opengl vertexes

		//obj model decode
		std::stringstream ssObjFile(fileContent);
		char szOneLine[256];
		std::string temp;
		while (!ssObjFile.eof())
		{
			memset(szOneLine, 0, 256);
			ssObjFile.getline(szOneLine,256);
			if (strlen(szOneLine)>0)
			{
				std::stringstream ssOneLine(szOneLine);
				if (szOneLine[0]=='v')
				{
					if (szOneLine[1]=='t')
					{
						//vertex coord
						ssOneLine >> temp;
						VertexInfo vi;
						ssOneLine >> vi.v[0];
						ssOneLine >> vi.v[1];
						texcoords.push_back(vi);
					}
					else if(szOneLine[1]=='n')
					{
						//normal
						ssOneLine >> temp;
						VertexInfo vi;
						ssOneLine >> vi.v[0];
						ssOneLine >> vi.v[1];
						ssOneLine >> vi.v[2];
						normals.push_back(vi);
					}
					else
					{
						//position
						ssOneLine >> temp;
						VertexInfo vi;
						ssOneLine >> vi.v[0];
						ssOneLine >> vi.v[1];
						ssOneLine >> vi.v[2];
						positions.push_back(vi);
					}
				}
				else if (szOneLine[0] == 'f')
				{
					//face
					ssOneLine >> temp;// 'f'
					std::string vertexStr;
					for (int i = 0; i<3; i++)
					{
						ssOneLine >> vertexStr;
						size_t pos = vertexStr.find_first_of('/');
						std::string positionIndexStr = vertexStr.substr(0, pos);
						size_t pos2 = vertexStr.find_first_of('/', pos + 1);
						std::string texcoordIndexStr = vertexStr.substr(pos + 1, pos2 - pos - 1);
						std::string normalIndexStr = vertexStr.substr(pos2 +1 , vertexStr.length() - pos2 - 1);
						VertexDefine vd;
						vd.positionIndex = atoi(positionIndexStr.c_str()) - 1;
						vd.texcoordIndex = atoi(texcoordIndexStr.c_str()) - 1;
						vd.normalIndex = atoi(normalIndexStr.c_str()) - 1;

						int nCurrentIndex = -1;//indexes
											   //check if exist
						size_t nCurrentVerticeCount = vertices.size();
					/*	for (size_t j = 0; j < nCurrentVerticeCount; j++)
						{
							if (vertices[j].positionIndex == vd.positionIndex&&
								vertices[j].texcoordIndex == vd.texcoordIndex&&
								vertices[j].normalIndex == vd.normalIndex)
							{
								nCurrentIndex = j;
								break;
							}
						}
						if (nCurrentIndex == -1)
						{*/
							//create new vertice
							nCurrentIndex = vertices.size();
							vertices.push_back(vd);//vertexes define
						//}
						objIndexes.push_back(nCurrentIndex);
					}
				}
			}
			
		}
	    int vertexCount = (int)vertices.size();
		mVertexBuffer = new vertexbuffer();
		mVertexBuffer->SetSize(vertexCount);

		
		for (int i = 0; i < vertexCount; i++)
		{
			float * temp = positions[vertices[i].positionIndex ].v;
			mVertexBuffer->SetPosition(i, temp[0], temp[1], temp[2]);
			temp = texcoords[vertices[i].texcoordIndex].v;
			mVertexBuffer->SetTexcoord(i, temp[0], temp[1]);
			 temp = normals[vertices[i].normalIndex].v;
			mVertexBuffer->SetNormal(i, temp[0], temp[1], temp[2]);
		}

		mShader = new shader;
		mShader->Init("res/shader/model.vs","res/shader/model.fs");
	}
}

model::model()
{
	
}

model::~model()
{
}

void model::Init(const char* filePath)
{
	LoadObjModel(filePath);
	mModelMatr = glm::translate(1.0f, 1.0f, 1.0f)* glm::scale(0.1f, 0.1f, 0.1f);
}

void model::SetTexture(const char * textPath)
{
	if (mShader)
	{
		mShader->SetTexure("U_Texture", textPath);
	}
}

void model::Draw(glm::mat4 & viewMatrix, glm::mat4 & projectionMatrix, float x, float y, float z)
{
	mModelMatr = glm::translate(0.0f, 0.0f, 0.0f)*glm::scale(0.1f, 0.1f, 0.1f);
	glEnable(GL_DEPTH_TEST);
	mShader->SetCameraPos(x, y, z);
	mVertexBuffer->Bind();
	mShader->Bind(glm::value_ptr(mModelMatr), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatrix));
	glDrawArrays(GL_TRIANGLES, 0, mVertexBuffer->mVertexCount);
	mVertexBuffer->Unbind();

}

void model::SetPosition(float x, float y, float z)
{
	//mModelMatr = glm::translate(x,y,z);
}
